//
//  main.cpp
//  多态练习
//
//  Created by 卜绎皓 on 2022/11/1.
//

//#include<iostream>
//#include<string>
//using namespace std;

//class Person
//{
//public:
//    void BuyTicket()
//    {
//        cout << "正常排队-全价买票" << endl;
//    }
//protected:
//    int _age;
//    string _name;
//};
//class Student : public Person
//{
//public:
//    void BuyTicket()
//    {
//        cout << "正常排队-半价买票" << endl;
//    }
//protected:
//    //...
//};
//class Soldier : public Person
//{
//public:
//    void BuyTicket()
//    {
//        cout << "优先排队-全价买票" << endl;
//    }
//protected:
//    //...
//};
//void Func(Person* ptr)
//{
//    ptr->BuyTicket();
//}
//
//int main()
//{
//    Person ps;
//    Student st;
//    Soldier sd;
//
//    Func(&ps);
//    Func(&st);
//    Func(&sd);
//
//    return 0;
//}
//#include<iostream>
//#include<string>
//using namespace std;
//
//class Person
//{
//public:
//    virtual void BuyTicket()
//    {
//        cout << "正常排队-全价买票" << endl;
//    }
//protected:
//    int _age;
//    string _name;
//};
//class Student : public Person
//{
//public:
//    virtual void BuyTicket()//重写或覆盖父类的虚函数
//    {
//        cout << "正常排队-半价买票" << endl;
//    }
//protected:
//    //...
//};
//class Soldier : public Person
//{
//public:
//    virtual void BuyTicket()//重写或覆盖父类的虚函数
//    {
//        cout << "优先排队-全价买票" << endl;
//    }
//protected:
//    //...
//};
//void Func(Person* ptr)//指针
//{
//    //多态 - ptr指向父类对象,调用父类的虚函数;指向子类对象,调用子类的虚函数
//    ptr->BuyTicket();
//}
//void Func(Person& ptr)//引用
//{
//    //多态 - ptr指向父类对象,调用父类的虚函数;指向子类对象,调用子类的虚函数
//    ptr.BuyTicket();
//}
////void Func(Person ptr)//对象
////{
////    ptr.BuyTicket();
////}
//
//int main()
//{
//    Person ps;
//    Student st;
//    Soldier sd;
//
//    Func(&ps);
//    Func(&st);
//    Func(&sd);
//
//    Func(ps);
//    Func(st);
//    Func(sd);
//
//    return 0;
//}

//#include<iostream>
//using namespace std;
//
////class A {};//AB为无关联的类
////class B {};
//class A {};//AB为关联的父子类
//class B : public A {};
//
//class Person
//{
//public:
//    virtual A* BuyTicket()
//    {
//        cout << "正常排队-全价买票" << endl;
//        return new A;
//    }
//protected:
//    int _age;
//    string _name;
//};
//class Student : public Person
//{
//public:
//    virtual B* BuyTicket()
//    {
//        cout << "正常排队-半价买票" << endl;
//        return new B;
//    }
//protected:
//    //...
//};
//void Func(Person& ptr)
//{
//    ptr.BuyTicket();
//}
//
//int main()
//{
//    Person ps;
//    Student st;
//
//    Func(ps);
//    Func(st);
//
//    return 0;
//}

//#include<iostream>
//using namespace std;
//
//class Person
//{
//public:
//    //~Person()
//    virtual ~Person()
//    {
//        cout << "~Person()" << endl;
//    }
//};
//class Student : public Person
//{
//public:
//    //~Student()
//    virtual ~Student()
//    {
//        cout << "~Student()" << endl;
//    }
//};
//
//int main()
//{
//    //普通场景
//    Person p;
//    Student s;
//
//    //new对象的特殊场景
//    Person* p1 = new Person;
//    Person* p2 = new Student;
//
//    delete p1;//p1->destructor() + operator delete(p1)
//    delete p2;//p2->destructor() + operator delete(p2)
//
//    return 0;
//}

//#include<iostream>
//#include<string>
//using namespace std;
//
//class Person
//{
//public:
//    virtual void BuyTicket()
//    {
//        cout << "正常排队-全价买票" << endl;
//    }
//protected:
//    int _age;
//    string _name;
//};
//class Student : public Person
//{
//public:
//    void BuyTicket()//可以不加virtual
//    {
//        cout << "正常排队-半价买票" << endl;
//    }
//protected:
//    //...
//};
//void Func(Person* ptr)
//{
//    ptr->BuyTicket();
//}
//
//int main()
//{
//    Person ps;
//    Student st;
//
//    Func(&ps);
//    Func(&st);
//
//    return 0;
//}

//#include<iostream>
//using namespace std;
//
//class Car
//{
//public:
//    virtual void Drive() final
//    {}
//};
//class Benz : public Car
//{
//public:
//    virtual void Drive()
//    {
//        cout << "Benz-舒适" << endl;
//    }
//};
//
//int main()
//{
//    return 0;
//}

//#include<iostream>
//using namespace std;
//
//class Car
//{
//public:
//    virtual void Drive() {}
//};
//class Benz : public Car
//{
//public:
//    //virtual void Drive() override//ok,重写
//    //{
//    //    cout << "Benz-舒适" << endl;
//    //}
//
//    //void Drive() override//ok,属于重写的例外
//    //{
//    //    cout << "Benz-舒适" << endl;
//    //}
//
//    virtual void Drive(int) override//err,没有完成重写
//    {
//        cout << "Benz-舒适" << endl;
//    }
//};
//int main()
//{
//    return 0;
//}

//#include<iostream>
//using namespace std;
//
//class Car//抽象类
//{
//public:
//    virtual void Drive() = 0;//纯虚函数
//};
//class Benz : public Car
//{
//public:
//    virtual void Drive()//重写纯虚函数
//    {
//        cout << "Benz-舒适" << endl;
//    }
//};
//class BMW : public Car
//{
//public:
//    virtual void Drive()//重写纯虚函数
//    {
//        cout << "BMW-操控" << endl;
//    }
//};
//
//int main()
//{
//    Benz bz;
//
//    Car* pBenz = new Benz;
//    pBenz->Drive();
//
//    Car* pBMW = new BMW;
//    pBMW->Drive();
//
//    return 0;
//}
#include <iostream>
using namespace std;

//class Base {
//public :
//
//    virtual void func1()
//    {
//        cout<<"Base::func1" <<endl;
//    }
//    virtual void func2()
//    {
//        cout<<"Base::func2" <<endl;
//    }
//private :
//    int a;
//};
//class Derive :public Base {
//public :
//virtual void func1()
//    {
//        cout<<"Derive::func1" <<endl;
//    }
//virtual void func3()
//    {
//        cout<<"Derive::func3" <<endl;
//    }
//virtual void func4()
//    {
//        cout<<"Derive::func4" <<endl;
//    }
//private :
//    int b;
//};
//
//typedef void(*VFPTR) ();
//void PrintVTable(VFPTR vTable[])
//{
//    // 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数
//    cout << " 虚表地址>" << vTable << endl;
//    for (int i = 0; vTable[i] != nullptr; ++i)
//    {
//        printf(" 第%d个虚函数地址 :0X%x,->", i, vTable[i]);
//        VFPTR f = vTable[i];
//        f();
//    }
//    cout << endl;
//}
//
//int main()
//{
//    Base b;
//    Derive d;
//    //思路：取出b、d对象的头4bytes，就是虚表的指针，前面我们说了虚函数表本质是一个存虚函数指针的指针数组，这个数组最后面放了一个nullptr
//    // 1.先取b的地址，强转成一个int*的指针
//    // 2.再解引用取值，就取到了b对象头4bytes的值，这个值就是指向虚表的指针
//    // 3.再强转成VFPTR*，因为虚表就是一个存VFPTR类型(虚函数指针类型)的数组。
//    // 4.虚表指针传递给PrintVTable进行打印虚表
//    // 5.需要说明的是这个打印虚表的代码经常会崩溃，因为编译器有时对虚表的处理不干净，虚表最后面没有放nullptr，导致越界，这是编译器的问题。我们只需要点目录栏的-生成-清理解决方案，再编译就好了。
//    VFPTR* vTableb = (VFPTR*)(*(int*)&b);
//    PrintVTable(vTableb);
//
//    VFPTR* vTabled = (VFPTR*)(*(int*)&d);
//    PrintVTable(vTabled);
//
//    return 0;
//}

class Base1 {
public:
    virtual void func1()
    {
        cout << "Base1::func1" << endl;
    }
    virtual void func2()
    {
        cout << "Base1::func2" << endl;
    }
private:
    int b1;
};

class Base2 {
public:
    virtual void func1()
    {
        cout << "Base2::func1" << endl;
    }
    virtual void func2()
    {
        cout << "Base2::func2" << endl;
    }
private:
    int b2;
};

class Derive : public Base1, public Base2 {
public:
    virtual void func1()
    {
        cout << "Derive::func1" << endl;
    }
    virtual void func3()
    {
        cout << "Derive::func3" << endl;
    }
private:
    int d1;
};

typedef void(*VFPTR) ();
void PrintVTable(VFPTR vTable[])
{
    cout << " 虚表地址>" << vTable << endl;
    for (int i = 0; vTable[i] != nullptr; ++i)
    {
        printf(" 第%d个虚函数地址 :0X%x,->", i, vTable[i]);
        VFPTR f = vTable[i];
        f();
    }
    cout << endl;
}
    
int main()
{
    Derive d;
    
    VFPTR* vTableb1 = (VFPTR*)(*(int*)&d);
    PrintVTable(vTableb1);
    
    VFPTR* vTableb2 = (VFPTR*)(*(int*)((char*)&d+sizeof(Base1)));
    PrintVTable(vTableb2);
    
    return 0;
}
